﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.IO;
using Visualization.DataModel;

namespace Visualization
{
	/// <summary>
	/// Interaction logic for VisualizationCreator.xaml
	/// </summary>
	public partial class VisualizationCreator : System.Windows.Controls.UserControl
	{
		public BackgroundWorker bgWorker = new BackgroundWorker();
		public VisualizationCreator()
		{
			this.InitializeComponent();
			bgWorker.WorkerReportsProgress = true;
			bgWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(bgWorker_DoWork);
			bgWorker.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(bgWorker_ProgressChanged);
            bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
		}

        void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if(e.Result != null){
                List<Object> results = (List<Object>)e.Result;
                if (((VisualizationType)results[1]).Equals(VisualizationType.Density))
                {
                    DensityGraph graph = new DensityGraph(System.Windows.Forms.Screen.AllScreens[(int)results[2]]);
                    graph.createGraph((Dictionary<int, SFPStep>)((List<Object>)results[0])[0]);
                }
                else if (((VisualizationType)results[1]).Equals(VisualizationType.Disagreement))
                {
                    DisagreementGraph graph = new DisagreementGraph(System.Windows.Forms.Screen.AllScreens[(int)results[2]]);
                    List<List<Point>> stepDataLists = ((List<List<Point>>)((List<Object>)results[0])[0]);
                    List<List<Point>> particleDataLists = ((List<List<Point>>)((List<Object>)results[0])[1]);
                    foreach (List<Point> lists in stepDataLists)
                        graph.createDisagreementGraph(lists, particleDataLists[stepDataLists.IndexOf(lists)], ((List<FileInfo>)((List<Object>)results[0])[2])[stepDataLists.IndexOf(lists)]);
                }
                else
                {
                    TrendingGraph graph = new TrendingGraph(System.Windows.Forms.Screen.AllScreens[(int)results[2]]);
                    List<IEnumerable<SFPStep>> stepsList = (List<IEnumerable<SFPStep>>)((List<Object>)results[0])[0];
                    foreach (IEnumerable<SFPStep> steps in stepsList)
                        graph.createTrend((List<SFPStep>)steps, ((List<FileInfo>)((List<Object>)results[0])[1])[stepsList.IndexOf(steps)]);
                }
            }
        }
		
		public List<Object> generateVisualization(VisualizationType type, int monitorNum, List<FileInfo> dataSrc){
            List<Object> returnData = new List<Object>();
            bgWorker.ReportProgress(0, "Fetching Data...");
			List<ParticleProvider> dataProviders = new List<ParticleProvider>();
            if (dataSrc.Count > 0)
            {
                foreach (FileInfo info in dataSrc)
                    dataProviders.Add(new ParticleProvider(info.FullName));
                if (type.Equals(VisualizationType.Density))
                {
                    List<SFPStep> steps = (List<SFPStep>)dataProviders[0].FetchRange(3, 2000);
                    bgWorker.ReportProgress(50, "Converting to indexed dictionary...");
                    Dictionary<int, SFPStep> newSteps = new Dictionary<int, SFPStep>();
                    foreach (SFPStep step in steps)
                        newSteps.Add(steps.IndexOf(step), step);
                    steps.Clear();
                    returnData.Add(newSteps);
                    bgWorker.ReportProgress(100, "Done! Starting post-processing...");
                    return returnData;
                }
                else if (type.Equals(VisualizationType.Disagreement))
                {
                    List<IEnumerable<SFPStep>> srcStepsList = new List<IEnumerable<SFPStep>>();
                    foreach (ParticleProvider provider in dataProviders)
                        srcStepsList.Add(provider.FetchRange(3, 10000));
                    List<List<Point>> particleDataLists = new List<List<Point>>();
                    List<List<Point>> stepDataLists = new List<List<Point>>();
                    bgWorker.ReportProgress(50, "Pre-processing step and particle data...");
                    foreach (IEnumerable<SFPStep> stepList in srcStepsList)
                    {
                        List<Point> stepData = new List<Point>();
                        List<Point> particleData = new List<Point>();
                        foreach (SFPStep step in stepList)
                        {
                            stepData.Add(new Point(step.X, step.Y));
                            particleData.Add(new Point(step.HighestProbabilityParticle.X, step.HighestProbabilityParticle.Y));
                        }
                        ((List<SFPStep>)stepList).Clear();
                        stepDataLists.Add(stepData);
                        particleDataLists.Add(particleData);
                    }
                    srcStepsList.Clear();
                    returnData.Add(stepDataLists);
                    returnData.Add(particleDataLists);
                    returnData.Add(dataSrc);
                    bgWorker.ReportProgress(100, "Done! Starting post-processing...");
                    return returnData;
                }
                else
                {
                    List<IEnumerable<SFPStep>> srcStepsList = new List<IEnumerable<SFPStep>>();
                    foreach (ParticleProvider provider in dataProviders)
                        srcStepsList.Add(provider.FetchRange(3, 10000));
                    returnData.Add(srcStepsList);
                    returnData.Add(dataSrc);
                    bgWorker.ReportProgress(100, "Done! Starting post-processing...");
                    return returnData;
                }
            }
            else
                return null;
		}

		private void bgWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
		{
			List<Object> args = (List<Object>)e.Argument;
            List<Object> results = new List<Object>();
            results.Add(generateVisualization((VisualizationType)args[0], (int)args[1], (List<FileInfo>)args[2])); 
            results.Add((VisualizationType)args[0]);
            results.Add((int)args[1]);
            e.Result = results;
		}

		private void bgWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
		{
			progressBar.Value = e.ProgressPercentage;
			status.Content = "Progress: " + e.UserState.ToString();
		}

        public enum VisualizationType : int
        {
            Density = 1,
            Disagreement = 2,
            Trending = 3
        }
	}
}